<template>
  <div class="container">
    <!-- 骨架屏 -->
    <el-skeleton v-if="loading && rangeData.rangeList.length === 0" :rows="6" animated />

    <!-- 靶场卡片列表 -->
    <div v-show="!loading || rangeData.rangeList.length > 0" class="main-content">
      <el-row :gutter="20" class="exam-row">
        <el-col v-for="item in rangeData.rangeList" :key="item.rangeId" :span="6">
          <el-card shadow="hover" @click="openChallengeDialog(item)" class="challenge-card">
            <template #header>
              <div class="card-header">
                <span class="text-contest-name">{{ item.rangeName }}</span>
                <el-tag v-if="isContainerRunning(item.rangeId)" type="success" size="small" class="active-tag">运行中</el-tag>
              </div>
            </template>
            <div class="card-content">
              <div class="meta-info">
                <div class="challenge-difficulty">
                  <el-tag :type="getDifficultyType(item.difficultyId)">
                    {{ getDifficultyText(item.difficultyId) }}
                  </el-tag>
                </div>
                <div class="challenge-type">
                  <el-tag type="info">{{ item.rangeType }}</el-tag>
                </div>
              </div>

              <div class="challenge-desc">
                <el-tooltip :content="item.rangeDesc" placement="bottom">
                  <span class="desc-text">{{ truncateDescription(item.rangeDesc) }}</span>
                </el-tooltip>
              </div>

              <div v-if="isContainerRunning(item.rangeId)" class="container-status">
                <div class="status-item">
                  <span class="label">访问地址:</span>
                  <span class="value">{{ getContainerAddress(item.rangeId) }}</span>
                </div>
                <div class="status-item">
                  <span class="label">剩余时间:</span>
                  <span class="value time-remaining">{{ formatTime(getRemainingTime(item.rangeId)) }}</span>
                </div>
              </div>
            </div>
          </el-card>
        </el-col>
      </el-row>
    </div>

    <!-- 弹窗：挑战详情 -->
    <el-dialog
        v-model="dialogVisible"
        :title="currentChallenge ? currentChallenge.rangeName : ''"
        width="50%"
        class="challenge-dialog"
        @closed="handleDialogClosed"
    >
      <div v-if="currentChallenge" class="challenge-details">
        <!-- 基本信息 -->
        <div class="challenge-info">
          <div class="info-item">
            <span class="label">类型:</span>
            <span class="value">{{ currentChallenge.rangeType }}</span>
          </div>
          <div class="info-item">
            <span class="label">难度:</span>
            <el-tag :type="getDifficultyType(currentChallenge.difficultyId)">
              {{ getDifficultyText(currentChallenge.difficultyId) }}
            </el-tag>
          </div>
        </div>

        <!-- 描述 -->
        <div class="challenge-description">
          <h3>靶场描述</h3>
          <p>{{ currentChallenge.rangeDesc }}</p>
        </div>

        <!-- 创建容器区域 -->
        <div v-if="!isContainerRunning(currentChallenge.rangeId)" class="container-actions">
          <el-button type="success" @click="startRange(currentChallenge.rangeId)" :loading="creatingContainer">
            创建容器
          </el-button>
        </div>

        <!-- 容器状态 -->
        <div v-if="isContainerRunning(currentChallenge.rangeId)" class="container-status-dialog">
          <div class="ip-port-container">
            <span class="label">访问地址:</span>
            <span class="ip-port">{{ getContainerAddress(currentChallenge.rangeId) }}</span>
            <el-tooltip content="复制地址" placement="top">
              <el-button icon="DocumentCopy" circle size="small" @click="copyAddress(getContainerAddress(currentChallenge.rangeId))" />
            </el-tooltip>
          </div>

          <div class="time-container">
            <el-tag type="info">剩余时间: {{ formatTime(getRemainingTime(currentChallenge.rangeId)) }}</el-tag>
            <el-button type="danger" @click="destroyContainer(currentChallenge.rangeId)" size="small"> 销毁容器 </el-button>
          </div>

          <div class="timeout-tip">
            <el-alert title="容器将在倒计时结束后自动销毁" type="warning" :closable="false" show-icon />
          </div>
        </div>

        <!-- Flag提交区域 -->
        <div class="flag-submission">
          <h3>提交Flag</h3>
          <el-input v-model="flagInput" placeholder="请输入获取到的flag值" class="flag-input" />
          <el-button type="primary" @click="submitFlag" :loading="isSubmitting">提交</el-button>
        </div>
      </div>
    </el-dialog>

    <!-- 返回顶部按钮 -->
    <el-backtop target=".main-content" :visibility-height="300" :bottom="80">
      <i class="el-icon-arrow-up"></i>
    </el-backtop>
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted, onUnmounted } from 'vue'
import {
  ElMessage,
  ElTooltip,
  ElBacktop,
  ElAlert,
  ElButton,
  ElCard,
  ElCol,
  ElRow,
  ElDialog,
  ElInput,
  ElTag,
  ElTooltip as ElTooltipComponent
} from 'element-plus'
import contestQuery from '@/api/modules/contestQuery'
import router from '@/router'
import containerMange from '@/api/Backend/containerMange'
import { userInfo } from '@/stores/userinfo'

const userStore = userInfo();


// 定义挑战数据结构
interface Challenge {
  rangeId: string | number
  rangeName: string
  rangeType: string
  difficultyId: number
  rangeDesc: string
}

// 容器状态接口
interface ContainerStatus {
  rangeId: string | number
  containerId: string | null
  challengeIpPort: string
  countdown: number | null
  countdownInterval: number | null
  containerCreated: boolean
  expiresAt?: number | null
}

// 使用专属键名保存容器状态，避免与其他页面冲突
const STORAGE_KEY = 'contestActiveContainers'

// 列表相关
const rangeData = ref<{
  rangeList: Challenge[]
}>({
  rangeList: []
})

const loading = ref(false)

// 弹窗与挑战详情
const dialogVisible = ref(false)
const currentChallenge = ref<Challenge | null>(null)

// 容器状态管理 - 每个靶场独立状态
const containerStatusMap = ref<Record<string | number, ContainerStatus>>({})

// 用户输入的 flag
const flagInput = ref('')

// 提交状态
const isSubmitting = ref(false)
const creatingContainer = ref(false)

// 当前考试ID
const contestId = ref()

onMounted(() => {
  contestId.value = userStore.onGoingContest
  if (!contestId.value) {
    router.replace('/contest/list')
  }
  restoreContainerStatuses()
  resetRange()
})

// 组件卸载时清除所有定时器
onUnmounted(() => {
  Object.values(containerStatusMap.value).forEach(status => {
    if (status.countdownInterval) {
      clearInterval(status.countdownInterval)
    }
  })
})

// 打开靶场详情对话框
const openChallengeDialog = (challenge: Challenge) => {
  currentChallenge.value = challenge
  dialogVisible.value = true

  // 初始化容器状态（如果不存在）
  if (!containerStatusMap.value[challenge.rangeId]) {
    containerStatusMap.value[challenge.rangeId] = {
      rangeId: challenge.rangeId,
      containerId: null,
      challengeIpPort: '',
      countdown: null,
      countdownInterval: null,
      containerCreated: false
    }
  }
}

// 弹窗关闭时的处理
const handleDialogClosed = () => {
  currentChallenge.value = null
  flagInput.value = ''
}

// 获取难度标签类型
const getDifficultyType = (difficulty: number) => {
  switch (difficulty) {
    case 1:
      return 'success'
    case 2:
      return 'warning'
    case 3:
      return 'danger'
    default:
      return 'info'
  }
}

// 获取难度文本
const getDifficultyText = (difficulty: number) => {
  switch (difficulty) {
    case 1:
      return '简单'
    case 2:
      return '中等'
    case 3:
      return '困难'
    default:
      return '未知'
  }
}

// 截断描述文本
const truncateDescription = (desc: string) => {
  if (!desc) return '暂无描述'
  return desc.length > 30 ? desc.substring(0, 30) + '...' : desc
}

// 获取靶场数据
const resetRange = () => {
  loading.value = true
  contestQuery
      .queryRange({ contestId: contestId.value })
      .then(res => {
        rangeData.value.rangeList = res.data as Challenge[]
      })
      .finally(() => {
        loading.value = false
      })
}

// 启动指定靶机
const startRange = async (rangeId: string | number) => {
  const status = containerStatusMap.value[rangeId]
  if (status?.containerCreated) {
    ElMessage.info('已有容器正在运行')
    return
  }

  creatingContainer.value = true
  try {
    const res = await containerMange.createStart({ rangeId })

    if (res.code === 200 && res.data) {
      containerStatusMap.value[rangeId] = {
        ...status,
        rangeId,
        containerId: res.data.containerId || null,
        challengeIpPort: res.data.socket || '',
        countdown: res.data.timeoutSeconds || 0,
        containerCreated: true,
        expiresAt: Date.now() + (res.data.timeoutSeconds * 1000)
      }

      startCountdownForContainer(rangeId, containerStatusMap.value[rangeId].expiresAt!)
      saveContainerStatuses()
      ElMessage.success('容器创建成功')
    } else {
      ElMessage.error(res.msg || '创建容器失败')
    }
  } catch (err: any) {
    console.error('创建容器失败:', err)
    ElMessage.error('创建容器失败: ' + (err.message || '请稍后再试'))
  } finally {
    creatingContainer.value = false
  }
}

// 销毁指定靶机的容器
const destroyContainer = async (rangeId: string | number) => {
  const status = containerStatusMap.value[rangeId]
  if (!status?.containerId) {
    ElMessage.error('无效的容器ID')
    return
  }

  try {
    await containerMange.destroy({ containerId: status.containerId })

    if (status.countdownInterval) {
      clearInterval(status.countdownInterval)
    }

    containerStatusMap.value[rangeId] = {
      rangeId,
      containerId: null,
      challengeIpPort: '',
      countdown: null,
      countdownInterval: null,
      containerCreated: false
    }

    saveContainerStatuses()
    ElMessage.success('容器已销毁')
  } catch (err: any) {
    console.error('销毁容器失败:', err)
    ElMessage.error('销毁容器失败: ' + (err.message || '请稍后再试'))
  }
}

// 提交 Flag
const submitFlag = async () => {
  if (isSubmitting.value) return

  if (!currentChallenge.value || !flagInput.value.trim()) {
    ElMessage.warning('请先选择靶场并输入flag')
    return
  }

  const rangeId = currentChallenge.value.rangeId
  const containerId = containerStatusMap.value[rangeId]?.containerId

  if (!containerId) {
    ElMessage.warning('当前靶场未创建容器')
    return
  }

  isSubmitting.value = true
  try {
    const res = await containerMange.compareFlag({
      containerId,
      inputFlag: flagInput.value.trim()
    })

    if (res.code === 200) {
      ElMessage.success('恭喜！Flag正确')
      // 停止倒计时
      if (containerStatusMap.value[rangeId]?.countdownInterval) {
        clearInterval(containerStatusMap.value[rangeId].countdownInterval!)
        containerStatusMap.value[rangeId].countdownInterval = null
      }
      // 销毁容器
      await destroyContainer(rangeId)
      // 关闭弹窗
      dialogVisible.value = false
      currentChallenge.value = null
    } else if (res.code === 501) {
      ElMessage.warning(res.msg || '时间到')
    } else {
      ElMessage.error(res.msg || 'Flag不正确，请再试一次')
    }
  } catch (err: any) {
    ElMessage.error('验证失败：' + (err.message || '请稍后再试'))
    console.error(err)
  } finally {
    isSubmitting.value = false
  }
}

// 为容器启动倒计时
const startCountdownForContainer = (rangeId: string | number, endTime: number) => {
  if (!containerStatusMap.value[rangeId]) {
    containerStatusMap.value[rangeId] = {
      rangeId,
      containerId: null,
      challengeIpPort: '',
      countdown: null,
      countdownInterval: null,
      containerCreated: false
    }
  }

  const status = containerStatusMap.value[rangeId]

  if (status.countdownInterval) {
    clearInterval(status.countdownInterval)
    status.countdownInterval = null
  }

  const updateCountdown = () => {
    const now = Date.now()
    const remaining = Math.max(0, Math.floor((endTime - now) / 1000))

    if (containerStatusMap.value[rangeId]) {
      containerStatusMap.value[rangeId].countdown = remaining
    }

    if (remaining <= 0) {
      if (status.countdownInterval) {
        clearInterval(status.countdownInterval)
      }
      destroyContainer(rangeId)
    }
  }

  updateCountdown()
  status.countdownInterval = window.setInterval(updateCountdown, 1000)
}

// 保存容器状态到本地存储
const saveContainerStatuses = () => {
  const activeContainers = Object.values(containerStatusMap.value)
      .filter(status => status.containerCreated)
      .map(status => ({
        rangeId: status.rangeId,
        containerId: status.containerId,
        challengeIpPort: status.challengeIpPort,
        countdown: status.countdown,
        containerCreated: status.containerCreated,
        expiresAt: status.expiresAt
      }))

  localStorage.setItem(STORAGE_KEY, JSON.stringify(activeContainers))
}

// 从本地存储恢复容器状态
const restoreContainerStatuses = () => {
  const savedContainers = localStorage.getItem(STORAGE_KEY)
  if (!savedContainers) return

  try {
    const containers = JSON.parse(savedContainers)
    const now = Date.now()

    containers.forEach((container: any) => {
      if (container.expiresAt && container.expiresAt > now) {
        const remainingSeconds = Math.floor((container.expiresAt - now) / 1000)

        containerStatusMap.value[container.rangeId] = {
          rangeId: container.rangeId,
          containerId: container.containerId,
          challengeIpPort: container.challengeIpPort,
          countdown: remainingSeconds,
          countdownInterval: null,
          containerCreated: true,
          expiresAt: container.expiresAt
        }

        startCountdownForContainer(container.rangeId, container.expiresAt)
      }
    })
  } catch (err) {
    console.error('恢复容器状态失败:', err)
    localStorage.removeItem(STORAGE_KEY)
  }
}

// 检查容器是否在运行
const isContainerRunning = (rangeId: string | number): boolean => {
  return containerStatusMap.value[rangeId]?.containerCreated || false
}

// 获取容器地址
const getContainerAddress = (rangeId: string | number): string => {
  return containerStatusMap.value[rangeId]?.challengeIpPort || ''
}

// 获取剩余时间
const getRemainingTime = (rangeId: string | number): number | null => {
  return containerStatusMap.value[rangeId]?.countdown || null
}

// 格式化倒计时时间
const formatTime = (seconds: number | null): string => {
  if (seconds === null || seconds <= 0) return '00:00:00'
  const hours = Math.floor(seconds / 3600)
  const minutes = Math.floor((seconds % 3600) / 60)
  const secs = seconds % 60
  return `${String(hours).padStart(2, '0')}:${String(minutes).padStart(2, '0')}:${String(secs).padStart(2, '0')}`
}

// 复制文本到剪贴板
const copyAddress = (text: string) => {
  navigator.clipboard.writeText(text).then(
      () => ElMessage.success('复制成功'),
      () => ElMessage.error('复制失败，请手动选择复制')
  )
}
</script>
<style scoped>
.container {
  padding: 20px;
  font-family: "Helvetica Neue", sans-serif;
}

.main-content {
  overflow: auto;
  max-height: calc(100vh - 60px);
  scrollbar-width: none;
}

.main-content::-webkit-scrollbar {
  display: none;
}

.exam-row {
  margin-bottom: 20px;
}

.challenge-card {
  margin-bottom: 20px;
  cursor: pointer;
  transition: transform 0.2s;
  height: 100%;
  display: flex;
  flex-direction: column;
}

.challenge-card:hover {
  transform: translateY(-5px);
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
}

.card-header {
  font-size: 16px;
  font-weight: bold;
  padding: 12px;
  border-bottom: 1px solid #ebebeb;
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.active-tag {
  margin-left: 8px;
}

.card-content {
  padding: 12px;
  flex: 1;
  display: flex;
  flex-direction: column;
}

.meta-info {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-bottom: 12px;
}

.challenge-difficulty,
.challenge-type {
  display: inline-block;
}

.challenge-desc {
  margin: 10px 0;
  flex: 1;
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
  line-height: 1.5;
  color: #666;
  font-size: 13px;
}

.desc-text {
  color: #666;
  font-size: 13px;
}

.container-status {
  margin-top: 12px;
  padding-top: 12px;
  border-top: 1px dashed #eee;
}

.status-item {
  display: flex;
  margin-bottom: 6px;
  font-size: 13px;
}

.status-item .label {
  color: #666;
  min-width: 60px;
}

.status-item .value {
  color: #333;
  word-break: break-all;
}

.time-remaining {
  color: #67C23A;
  font-family: monospace;
}

/* 弹窗样式 */
.challenge-details {
  padding: 0 10px;
}

.challenge-info {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 12px;
  margin-bottom: 20px;
}

.info-item {
  display: flex;
  align-items: center;
}

.info-item .label {
  font-weight: bold;
  margin-right: 8px;
  color: #666;
  min-width: 70px;
}

.info-item .value {
  color: #333;
}

.challenge-description {
  margin: 20px 0;
  padding: 15px;
  border-radius: 4px;
}

.challenge-description h3 {
  margin-top: 0;
  margin-bottom: 10px;
}

.challenge-description p {
  margin: 0;
  line-height: 1.6;
}

.container-actions {
  margin: 20px 0;
  text-align: center;
}

.container-status-dialog {
  margin-top: 20px;
  padding-top: 20px;
  border-top: 1px solid #eee;
}

.ip-port-container {
  display: flex;
  align-items: center;
  margin-bottom: 15px;
}

.ip-port-container .label {
  font-weight: bold;
  margin-right: 8px;
  color: #666;
}

.ip-port {
  margin-right: 10px;
  color: #409EFF;
  font-family: monospace;
  word-break: break-all;
}

.time-container {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 15px;
}

.timeout-tip {
  margin-top: 15px;
}

.flag-submission {
  margin-top: 20px;
}

.flag-input {
  width: 100%;
  margin-bottom: 10px;
}

@media (max-width: 1200px) {
  .el-col {
    width: 50%;
  }
}

@media (max-width: 768px) {
  .el-col {
    width: 100%;
  }

  .challenge-dialog {
    width: 90%;
  }

  .challenge-info {
    grid-template-columns: 1fr;
  }

  .ip-port-container {
    flex-wrap: wrap;
    gap: 8px;
  }
}
</style>
